package com.shrfid.rfidsdk.tag.uhf;


import com.rfid.common.log.LogUtils;
import com.shrfid.rfidsdk.tag.base.BaseDecoder;
import com.shrfid.rfidsdk.uitls.ReadTagUtils;

import java.nio.ByteBuffer;


/**
 * 串口数据解析器
 */
public class UHFDecoder extends BaseDecoder<UHFCommand, UHFResponseFrame, UHFInventoryResponse> {

    private static final String TAG = "READERSDK";

    private static final int READ_LEN = 1;
    private static final int READ_ADDRESS = 2;
    private static final int READ_CMD = 3;
    private static final int READ_STATUS = 4;
    private static final int READ_INFO = 5;
    private static final int READ_CRC = 6;

    /**
     * 当前解析状态
     */
    private int state = READ_LEN;
    private ByteBuffer infoBuffer;

    public UHFDecoder(UHFCommand baseCommand) {
        super(baseCommand);
    }

    /**
     * 解析串口数据
     *
     * @param data
     */
    public synchronized void decode(byte[] data) {
        if (data == null) {
            return;
        }

        for (int i = 0; i < data.length; i++) {
            byte b = data[i];
            switch (state) {
                case READ_LEN:
                    //读取长度正常
                    if (b > 0) {
                        // LogUtils.logI("数据长度为:" + b);
                        responseFrame = new UHFResponseFrame();
                        responseFrame.setLen(b);
                        state = READ_ADDRESS;//长度正常进入读取地址状态
                    } else {
                        //异常状态
                        // LogUtils.logI("读取长度异常:" + b);
                        resetState(true);
                    }
                    break;
                case READ_ADDRESS:
                    //响应数据已经初始化
                    if (responseFrame != null) {
                        // LogUtils.logI("address:" + b);
                        responseFrame.setAddress(b);
                        state = READ_CMD;//长度正常进入读取cmd状态
                    } else {
//                        ALogger.d("读取address异常");
                        //异常状态
                        resetState(true);
                    }
                    break;
                case READ_CMD:
                    //响应数据已经初始化
                    if (responseFrame != null) {
                        //赋值cmd
                        responseFrame.setCmd(b);
                        state = READ_STATUS;
                    } else {
                        // LogUtils.logI("读取CMD异常");
                        //异常状态
                        resetState(true);
                    }
                    break;
                case READ_STATUS:
                    //响应数据已经初始化
                    if (responseFrame != null) {
                        // LogUtils.logI("读取状态:" + b);
                        responseFrame.setStatus(b);
                        int infoLen = responseFrame.getLen() - 5;

                        if (infoLen > 0) {
                            //  LogUtils.logI("长度正常进入读取INFO状态");
                            infoBuffer = ByteBuffer.allocate(infoLen);
                            //长度正常进入读取INFO状态
                            state = READ_INFO;
                        } else {
                            // LogUtils.logI("没有info直接读取crc");
                            //没有info直接读取crc
                            state = READ_CRC;
                        }
                    } else {
                        //异常状态
                        // LogUtils.logI("读取状态异常");
                        resetState(true);
                    }
                    break;
                case READ_INFO:
                    //响应数据已经初始化并且infoBuffer已经初始化
                    if (responseFrame != null && infoBuffer != null) {
                        //  LogUtils.logI("读取info:" + b);
                        //如果这次加入数据后满了就把缓冲数据放入,并且置空缓冲
                        if ((infoBuffer.position() + 1) == infoBuffer.limit()) {
                            infoBuffer.put(b);
                            responseFrame.setParams(infoBuffer.array());
                            infoBuffer = null;
                            //长度正常进入读取READ_CRC状态
                            state = READ_CRC;
                        } else if (infoBuffer.position() < infoBuffer.limit()) {
                            infoBuffer.put(b);
                        }
                    } else {
                        // LogUtils.logI("读取info异常");
                        //异常状态
                        resetState(true);
                    }
                    break;
                case READ_CRC:
                    //响应数据已经初始化并且infoBuffer已经初始化
                    if (responseFrame != null) {
                        byte[] crc = responseFrame.getCrc();
                        //命令为空赋值高位
                        if (crc == null) {
                            // LogUtils.logI("读取CRC高位:" + b);
                            crc = new byte[2];
                            crc[0] = b;
                            responseFrame.setCrc(crc);
                        } else {
                            // LogUtils.logI("读取CRC低位:" + b);
                            crc[1] = b;
                            if (responseFrame.checkSelf()) {
                                LogUtils.v("read: " + ReadTagUtils.bytesToHexString(responseFrame.toBytes()));
                                decodeResponse(responseFrame);
                            }
                            //解析完一帧,重置状态
                            resetState(false);
                        }
                    } else {
//                        ALogger.d("读取CRC异常");
                        //异常状态
                        resetState(true);
                    }
                    break;
            }
        }
    }

    /**
     * 回到初始状态
     */
    private void resetState(boolean isError) {
        state = READ_LEN;
        responseFrame = null;
        if (isError) {
//            Log.d(TAG, "重置状态");
        }
    }

    @Override
    public UHFInventoryResponse createResponseData() {
        //根据不同命令生成不同返回数据
        byte cmd = responseFrame.getCmd();
        //如果之前没有说明这是一条命令第一个响应帧
        switch (cmd) {
            //盘点
            case 0x01:
                return new UHFInventoryResponse();
        }
        return null;
    }
}
